package cn.iocoder.yudao.module.digital.service.cardchannel.impl.bh;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.digital.dal.dataobject.cardkeyorder.CardkeyOrderDO;
import cn.iocoder.yudao.module.digital.dal.dataobject.cardkeyorder.CardkeyOrderProductDO;
import cn.iocoder.yudao.module.digital.enums.cardkeysecret.CardKeySourceEnum;
import cn.iocoder.yudao.module.digital.service.cardchannel.ICardChannel;
import cn.iocoder.yudao.module.digital.service.cardchannel.model.*;
import cn.iocoder.yudao.module.digital.service.cardchannel.model.common.*;
import cn.iocoder.yudao.module.digital.service.cardkeyorder.CardkeyOrderService;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 黑鹰实现
 */

@Component(value = "CardChannelBHImpl")
@Slf4j
public class CardChannelBHImpl implements ICardChannel {
    @Resource
    private ICardKeyThirdPartyBHApi bhApi;

    @Lazy
    @Resource
    private CardkeyOrderService cardkeyOrderService;

    @Override
    public CdkGenCardResult createAggregatedOrder(CdkGenCardReq req) {
        // 不支持
        throw new UnsupportedOperationException();
    }

    @Override
    public CdkGenCardResult createMultipleQuantitiesOrder(CdkGenCardReq req) {
        // 不支持
        throw new UnsupportedOperationException();
    }

    @Override
    public CdkGenCardResult createSingleQuantitiesOrder(CdkGenCardReq req) {
        Assert.isTrue(req.getProducts().size() == 1);
        final CdkGenCardReq.Product product = req.getProducts().get(0);
        Assert.isTrue(product.getQuantity() == 1);

        final String productNo = product.getProductNo();
        final String currencyCode = product.getCurrencyCode();
        final Integer buyDenomination = product.getBuyDenomination();
        final String cardOrderId = req.getCardOrderId();
        log.info("黑鹰生成卡密-开始, cardOrderId = {}, productNo = {}, buyDenomination = {}", cardOrderId, productNo, buyDenomination);

        final GenerateEGiftResponseWrapper generateCardResult;
        try {
            final GenerateEGiftRequest request = createGenerateEGiftRequestDTO(cardOrderId, buyDenomination, productNo);
            final GenerateEGiftRequestWrapper requestWrapper = new GenerateEGiftRequestWrapper(request, cardOrderId, productNo, buyDenomination, currencyCode);
            generateCardResult = bhApi.generateCard(requestWrapper);
        } catch (Exception e) {
            final String errorMsg = StrUtil.format("黑鹰生成卡密-提交或查询异常, cardOrderId = {}, productNo = {}, buyDenomination = {}", cardOrderId, productNo, buyDenomination);
            log.error(errorMsg, e);
            return new CdkGenCardResult(CdkOrderStatusEnum.QUERY_EXCEPTION, errorMsg);
        }

        if (generateCardResult.isGenerateEGiftSuccess()) {
            // 提交成功
            if (generateCardResult.getGetAccountResponseWrapper() != null && generateCardResult.getGetAccountResponseWrapper().isSuccess()) {
                // 查询成功
                final String channelCardOrderId = parseAccountId(generateCardResult.getGenerateEGiftResponse().getAccountId());
                final CdkGenCardResult cardResult = toCdkGenCardResult(generateCardResult.getGetAccountResponseWrapper(), cardOrderId, channelCardOrderId);
                log.info("黑鹰生成卡密-查询订单成功, cardOrderId = {}, productNo = {}, buyDenomination = {}, cardResult = {}",
                        cardOrderId, productNo, buyDenomination, JsonUtils.toJsonString(cardResult));
                return cardResult;
            } else {
                log.error("黑鹰生成卡密-查询订单失败, cardOrderId = {}, productNo = {}, buyDenomination = {}, generateCardResult = {}",
                        cardOrderId, productNo, buyDenomination, JsonUtils.toJsonString(generateCardResult));
                final String errorMsg = getErrorMsg(generateCardResult);
                return new CdkGenCardResult(CdkOrderStatusEnum.QUERY_FAILURE, errorMsg);
            }
        } else {
            // 提交失败
            log.error("黑鹰生成卡密-提交失败, cardOrderId = {}, productNo = {}, buyDenomination = {}, generateCardResult = {}",
                    cardOrderId, productNo, buyDenomination, JsonUtils.toJsonString(generateCardResult));
            final String errorMsg = getErrorMsg(generateCardResult);
            return new CdkGenCardResult(CdkOrderStatusEnum.SUBMIT_FAILURE, errorMsg);
        }
    }

    private CdkGenCardResult toCdkGenCardResult(GetAccountResponseWrapper getAccountResponseWrapper, String cardOrderId, String channelCardOrderId) {
        final List<CdkCardSecret> cardSecrets = new ArrayList<>();
        final CdkOrderStatusEnum orderStatus;

        final String status = getAccountResponseWrapper.getResponse().getStatus();
        if ("ACTIVATED".equals(status)) {
            // 创建卡密-成功
            orderStatus = CdkOrderStatusEnum.CARD_SUCCESS;
            final CdkCardSecret cardSecret = parseCdkSecret(cardOrderId, getAccountResponseWrapper);
            cardSecrets.add(cardSecret);
        } else {
            orderStatus = CdkOrderStatusEnum.CARD_PROCESSING;
        }

        final CdkGenCardResult cardResult = CdkGenCardResult.builder()
                .channelCardOrderId(channelCardOrderId)
                .channelInnerOrderId(channelCardOrderId)
                .orderStatus(orderStatus)
                .cards(cardSecrets)
                .build();

        return cardResult;
    }

    private CdkCardSecret parseCdkSecret(String cardOrderId, GetAccountResponseWrapper getAccountResponseWrapper) {
        // 查询卡密订单
        final CardkeyOrderDO cardOrder = cardkeyOrderService.getCardKeyOrder(cardOrderId);
        final List<CardkeyOrderProductDO> products = cardOrder.getProducts();
        final String productNo = products.get(0).getProductNo();

        final GetAccountResponse getAccountResponse = getAccountResponseWrapper.getResponse();

        final String entityId = getAccountResponse.getEntityId();
        final String eGiftId = parseAccountId(entityId);

        final CdkCardSecret cdkSecret = new CdkCardSecret();
        cdkSecret.setCardDetailData(getAccountResponseWrapper.getResponseData());

        cdkSecret.setProductNo(productNo);
        cdkSecret.setCurrencyCode(getAccountResponse.getCurrency());
        cdkSecret.setBuyDenomination(getAccountResponse.getActivationAmount().multiply(new BigDecimal(100)).intValue()); // 转换为分

        cdkSecret.setEGiftId(eGiftId);
        cdkSecret.setCardNumber(getAccountResponse.getActivationAccountNumber()); // (Card) Serial Number
        cdkSecret.setCode(getAccountResponse.getAccountNumber()); // Redeem Code
        cdkSecret.setPin(getAccountResponse.getSecurityCode()); // Security Pin of an Account

//        final String cardAccountId = parseAccountId(generateEGiftResponse.getAccountId());
//        final String retrievalReferenceNumber = generateEGiftResponse.getRetrievalReferenceNumber();
//        cdkSecret.setGetCardSecretApiRecordId(getAccountResponseWrapper.getApiRecordId());
//        cdkSecret.setRequestId(generateEGiftRequestId);
//        cdkSecret.setCardAccountId(cardAccountId);
//        cdkSecret.setRetrievalReferenceNumber(retrievalReferenceNumber);
        return cdkSecret;
    }

    private String getErrorMsg(GenerateEGiftResponseWrapper responseWrapper) {
        if (!responseWrapper.isGenerateEGiftSuccess()) {
            // 生成卡密失败
            final String errorMsg = responseWrapper.getGenerateEGiftErrorMsg();
            return errorMsg;
        } else {
            final GetAccountResponseWrapper getAccountResponseWrapper = responseWrapper.getGetAccountResponseWrapper();
            if (!getAccountResponseWrapper.isSuccess()) {
                // 查询卡密账户失败
                final String errorMsg = getAccountResponseWrapper.getErrorMsg();
                return errorMsg;
            }
        }
        return null;
    }

    private String parseAccountId(String urlString) {
        // 找到accountId参数在URL中的起始位置
        int accountIdIndex = urlString.indexOf("accountId=");

        // 如果找到了accountId参数
        if (accountIdIndex != -1) {
            // 截取accountId参数值
            final String accountId = urlString.substring(accountIdIndex + "accountId=".length());
            return accountId;
        }
        return null;
    }

    private GenerateEGiftRequest createGenerateEGiftRequestDTO(String orderNo, Integer denomination,
                                                               String productNo) {
        final GenerateEGiftRequest generateCardRequest = new GenerateEGiftRequest();
        final String giftAmount = new BigDecimal(denomination).divide(new BigDecimal(100)).toPlainString(); // 分转换为元
        generateCardRequest.setGiftAmount(giftAmount);
        generateCardRequest.setProductConfigurationId(productNo);
//        final GenerateEGiftRequest.User purchaserInfo = new GenerateEGiftRequest.User();
//        final int countryIndex = cardKeyConfig.getCountries().size() > 1 ? RandomUtil.randomInt(0, cardKeyConfig
//        .getCountries().size() - 1) : 0;
//        final CardKeyConfig.Country country = cardKeyConfig.getCountries().get(countryIndex);
//        final int stateCodeIndex = country.getStateCodes().size() > 1 ? RandomUtil.randomInt(0, country
//        .getStateCodes().size() - 1) : 0;
//        final String stateCode = country.getStateCodes().get(stateCodeIndex);
//        purchaserInfo.setState(stateCode);
//        purchaserInfo.setCountryCode(country.getCountryCode());
//        generateCardRequest.setPurchaserInfo(purchaserInfo);

        generateCardRequest.setEGiftDetails(new GenerateEGiftRequest.EGiftDetails());
        generateCardRequest.getEGiftDetails().setAdditionalAttributes(Arrays.asList(new GenerateEGiftRequest.AdditionalAttribute("UMS.62.5", "String",
                orderNo)));

        return generateCardRequest;
    }

    @Override
    public CdkGenCardResult queryOrder(String cardOrderId, String channelCardOrderId) {
        final GetAccountResponseWrapper getAccountResponseWrapper = bhApi.queryOrder(cardOrderId, channelCardOrderId);
        final CdkGenCardResult cardResult = toCdkGenCardResult(getAccountResponseWrapper, cardOrderId, channelCardOrderId);
        return cardResult;
    }

    /********************product********************/

    @Override
    public List<CdkProduct> getAllProducts() {
        final ExecutorService generateSecretExecutor = ThreadUtil.newFixedExecutor(
                8, "checkGenCardInTestEnv", true);
        final List<CdkProduct> products = new ArrayList<>();
        final List<String> productIdAllList = new ArrayList<>();

        // 获取分类
        final ProductCatalogsResponse getProductCatalogs = bhApi.getGetProductCatalogs();
        final List<ProductCatalogsResponse.Result> results = getProductCatalogs.getResults();

        for (ProductCatalogsResponse.Result result : results) {
            // 获取分类详情
            final String entityIdUrl = result.getEntityId();
            final ProductCatalogResponse catalogResponse = bhApi.getGetProductCatalog(entityIdUrl);
            final List<String> productIds = catalogResponse.getDetails().getProductIds();
            productIdAllList.addAll(productIds);
        }

        // 查询每一个商品
        final AtomicInteger allProductNum = new AtomicInteger();
        final AtomicInteger successProductNum = new AtomicInteger();
        final CountDownLatch latch = new CountDownLatch(productIdAllList.size());
        for (String productIdUrl : productIdAllList) {
            generateSecretExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        final ProductResponseWrapper productWrapper = bhApi.getProduct(productIdUrl);
                        allProductNum.getAndIncrement();

                        final List<CdkProduct> productList = convertToCdkProduct(
                                productWrapper, allProductNum, successProductNum);
                        if (CollUtil.isNotEmpty(productList)) {
                            products.addAll(productList);
                        }
                    } catch (Exception e) {
                        log.error(String.format("黑鹰获取卡密商品-异常, productIdUrl = %s", productIdUrl), e);
                    } finally {
                        latch.countDown();
                    }
                }
            });
        }

        try {
            latch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        log.info("黑鹰获取卡密商品-完成, allProductNum = {}, successProductNum = {}",
                allProductNum.get(), successProductNum.get());

        return products;
    }

    private List<CdkProduct> convertToCdkProduct(ProductResponseWrapper productWrapper,
                                                 AtomicInteger allProductNum,
                                                 AtomicInteger successProductNum) {
        final List<CdkProduct> products = new ArrayList<>();

        final ProductResponse product = productWrapper.getResponse();
        final Set<String> provisioningTypeSet = product.getDetails().getFulfillmentCharacteristics().stream()
                .map(v -> v.getProvisioningType()).collect(Collectors.toSet());
        final Set<String> redemptionOptionSet = product.getDetails().getRedemptionCharacteristics()
                .getRedemptionOptions().stream().collect(Collectors.toSet());
        final Set<String> fulfillmentMethodSet = product.getDetails().getFulfillmentCharacteristics().stream()
                .map(v -> v.getFulfillmentMethod()).collect(Collectors.toSet());

        final String productName = product.getSummary().getProductName();
        final String currency = product.getSummary().getCurrency();
        final String entityId = product.getEntityId().substring(product.getEntityId().lastIndexOf("/") + 1);
        final String productLineId = product.getSummary().getProductLineId()
                .substring(product.getSummary().getProductLineId().lastIndexOf("/") + 1);
        final String universalProductCode = product.getSummary().getUniversalProductCode();
        final String locale = product.getSummary().getLocale();
        final ProductResponse.ActivationCharacteristics activationCharacteristics =
                product.getDetails().getActivationCharacteristics();
        final boolean variableValue = activationCharacteristics.getIsVariableValue();
        final BigDecimal baseValueAmount = activationCharacteristics.getBaseValueAmount();
        final BigDecimal maxValueAmount = activationCharacteristics.getMaxValueAmount();

        if (!provisioningTypeSet.contains("DIGITAL")) {
            // 非数字卡
            log.warn("黑鹰获取卡密商品-非数字卡, productNum = {}, productName = {}, currency = {}, " +
                            "provisioningTypeSet = {}, redemptionOptionSet = {}, fulfillmentMethodSet = {}",
                    allProductNum, productName, currency, provisioningTypeSet, redemptionOptionSet,
                    fulfillmentMethodSet);
            return null;
        }

//        if (!redemptionOptionSet.contains("ON_LINE")) {
//            // 不能在网上兑换
//            log.warn("获取卡密商品-不能在网上兑换, productNum = {}, productName = {}, currency = {}, provisioningTypeSet = {},
//            redemptionOptionSet = {}, fulfillmentMethodSet = {}",
//                    allProductNum, productName, currency, provisioningTypeSet, redemptionOptionSet,
//                    fulfillmentMethodSet);
//            return;
//        }

        if (!fulfillmentMethodSet.contains("EMAIL") && !fulfillmentMethodSet.contains("SMS")) {
            // 非邮件/短信
            //  && !fulfillmentMethodSet.contains("URL") && !fulfillmentMethodSet.contains("IMAGEDATA")
            log.warn("黑鹰获取卡密商品-非邮件或短信履行方式, productNum = {}, productName = {}, currency = {}, " +
                            "provisioningTypeSet = {}, redemptionOptionSet = {}, fulfillmentMethodSet = {}",
                    allProductNum, productName, currency, provisioningTypeSet, redemptionOptionSet,
                    fulfillmentMethodSet);
            return null;
        }

        final List<ProductResponse.ProductConfigurations> configurations =
                product.getDetails().getProductConfigurations();
        for (ProductResponse.ProductConfigurations configuration : configurations) {
            final String configurationStatus = configuration.getConfigurationStatus();
            final String productNo = configuration.getConfigurationId();
            if (!"ACTIVATED".equals(configurationStatus)) {
                // 非激活
                log.warn("黑鹰获取卡密商品-未激活, productNum = {}, productName = {}, currency = {}, " +
                                "configurationName = {}, productNo = {}",
                        allProductNum, productName, currency, configuration.getConfigurationName(), productNo);
                continue;
            }

            successProductNum.incrementAndGet();
            log.info("黑鹰获取卡密商品-成功, productNum = {}, productName = {}, currency = {}, " +
                            "configurationName = {}, productNo = {}",
                    allProductNum, productName, currency, configuration.getConfigurationName(), productNo);

            final CdkProduct cdkProduct = new CdkProduct();
            cdkProduct.setSource(CardKeySourceEnum.BLACK_HAWK_API.getValue());
            cdkProduct.setProductNo(productNo);
            cdkProduct.setProductName(configuration.getConfigurationName());
            if (StringUtil.isNotEmpty(configuration.getConfigurationDescription())) {
                cdkProduct.setProductDescription(configuration.getConfigurationDescription());
            } else {
                cdkProduct.setProductDescription(product.getDetails().getProductDescription());
            }
            cdkProduct.setEntityId(entityId);
            cdkProduct.setItemId(String.valueOf(configuration.getItemId()));
            cdkProduct.setProductLineId(productLineId);
            cdkProduct.setConfigurationId(configuration.getConfigurationId());
            cdkProduct.setUpc(universalProductCode);
            final LocalDateTime startDate = parseDate(configuration.getStartDate());
            cdkProduct.setStartDate(startDate);
            final LocalDateTime endDate = parseDate(configuration.getEndDate());
            cdkProduct.setEndDate(endDate);
            cdkProduct.setLocale(locale);
            cdkProduct.setCurrencyCode(currency);
            cdkProduct.setCustomDenomination(variableValue);
            if (baseValueAmount != null) {
                final int denominationMin = baseValueAmount.multiply(new BigDecimal(100)).intValue();
                cdkProduct.setDenominationMin(denominationMin);
            }
            if (maxValueAmount != null) {
                final int denominationMax = maxValueAmount.multiply(new BigDecimal(100)).intValue();
                cdkProduct.setDenominationMax(denominationMax);
            }
            if (!variableValue && cdkProduct.getDenominationMin().equals(cdkProduct.getDenominationMax())) {
                // 固定面额
                cdkProduct.setDenominationFixed(cdkProduct.getDenominationMin());
            }
            final String fulfillmentMethod = String.join(",", fulfillmentMethodSet);
            cdkProduct.setFulfillmentMethod(fulfillmentMethod);

            final String redemptionOptions = String.join(",", redemptionOptionSet);
            cdkProduct.setRedemptionOptions(redemptionOptions);
            cdkProduct.setProductDetailData(productWrapper.getResponseContent());
            if (CollUtil.isNotEmpty(configuration.getProductImages())) {
                cdkProduct.setImageUrls(JsonUtils.toJsonString(configuration.getProductImages()));
            }

            products.add(cdkProduct);
        }

        return products;
    }

    private LocalDateTime parseDate(String dateTimeString) {
        if (StringUtil.isEmpty(dateTimeString)) {
            return null;
        }

        // 创建 DateTimeFormatter 对象，指定日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

        // 解析字符串为 ZonedDateTime 对象（带有时区信息）
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateTimeString, formatter);

        // 转换为本地时间（UTC+8）
        LocalDateTime localDateTime = zonedDateTime.withZoneSameInstant(ZoneId.of("Asia/Shanghai")).toLocalDateTime();

        return localDateTime;
    }

}
